#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <mysql/mysql.h>

#define ENTER 13
#define BACKSPACE 8

//MySQL variables
static char *sqlServer = "localhost"; /* server host (default=localhost) */
static char *sqlUser = "root"; /* username (default=login name) */
static char *sqlPassword = ""; /* password (default=none) */
static unsigned int sqlPort = 3306; /* port number (use built-in value) */
static char *sqlSocket = NULL; /* socket name (use built-in value) */
static char *sqlDb = "advanse"; /* database name (default=none) */
static unsigned int sqlFlags = 0; /* connection flags (none) */

//structures
typedef struct {
    int template_id;
    int user_project_id;
} SizeEstimate;

typedef struct {
    int newobject_id;
    int template_id;
    char function_name[100];
    int objectsize_id;
} NewObject;

typedef struct {
    int baseAddition_id;
    int template_id;
    char function_name[100];
    int objectsize_id;
} BaseAddition;

typedef struct {
    int reusedobject_id;
    int template_id;
    char function_name[100];
    float function_lines;
} ReusedObject;

typedef struct {
    int baseSize;
    int LOCDeleted;
    int LOCModified;
} BaseProgram;

//functions
int stGetObjectSizeID(int type, int size)
{
    MYSQL *conn;
    MYSQL_RES *result;
    MYSQL_ROW row;
    MYSQL_FIELD *field;
    conn = mysql_init(NULL);
    int num_fields, i, objectSizeID;
    
    if(mysql_real_connect(conn, sqlServer, sqlUser, sqlPassword, sqlDb, 0, NULL, 0) != NULL)
    {  
        char check[1000];
        sprintf(check, "SELECT objectsize_id FROM objectsize WHERE type_id = %d AND size_id = %d LIMIT 1", type, size);
        mysql_query(conn, check);
        result = mysql_store_result(conn);
        
        num_fields = mysql_num_fields(result);
        while ((row = mysql_fetch_row(result)))
        {
            for(i = 0; i < num_fields; i++)
            {
                char value[100];
                sprintf(value,"%s", row[i] ? row[i] : "NULL");
                
                objectSizeID = atoi(value);
            }
        }
    }
    else
    {
        printf("DATABASE CONNECTION ERROR!");
    }
    
    mysql_free_result(result);
    mysql_close(conn);
    
    return objectSizeID;
}

int stSetNewObject(NewObject newObject, int type, int size)
{
    
    MYSQL *conn;    
    conn = mysql_init(NULL);
    int success = 0;
    
    newObject.objectsize_id = stGetObjectSizeID(type,size);
    
    if(mysql_real_connect(conn, sqlServer, sqlUser, sqlPassword, sqlDb, 0, NULL, 0) != NULL)
    {        
        char query[1000];
        sprintf(query, "INSERT INTO newobject (template_id,function_name,objectsize_id) VALUES(%d,\"%s\",%d)",
            newObject.template_id,
            newObject.function_name,
            newObject.objectsize_id);
        if(mysql_query(conn, query) != 0)
        {
            success = 1;
        }
    }
    else
    {
        printf("DATABASE CONNECTION ERROR!");
    }
    
    return success;
}

int stSetReusedObject(ReusedObject reusedObject)
{

    MYSQL *conn;    
    conn = mysql_init(NULL);
    int success = 0;
    
    if(mysql_real_connect(conn, sqlServer, sqlUser, sqlPassword, sqlDb, 0, NULL, 0) != NULL)
    {        
        char query[1000];
        sprintf(query, "INSERT INTO reusedobject (template_id,function_name,function_lines) VALUES(%d,\"%s\",%f)",
            reusedObject.template_id,
            reusedObject.function_name,
            reusedObject.function_lines);
        if(mysql_query(conn, query) != 0)
        {
            success = 1;
        }
    }
    else
    {
        printf("DATABASE CONNECTION ERROR!");
    }
    
    return success;
}

float stGetTotalNewObjects(SizeEstimate sizeEstimate)
{
    MYSQL *conn;
    MYSQL_RES *result;
    MYSQL_ROW row;
    MYSQL_FIELD *field;
    conn = mysql_init(NULL);
    int num_fields, i;
    float total;
    
    if(mysql_real_connect(conn, sqlServer, sqlUser, sqlPassword, sqlDb, 0, NULL, 0) != NULL)
    {  
        char check[1000];
        sprintf(check, "SELECT SUM(objectsize.size) AS SUM FROM newobject, objecttype, objectsize WHERE newobject.objectsize_id = objectsize.objectsize_id AND objecttype.type_id = objectsize.type_id AND newobject.template_id = %d", sizeEstimate.template_id);
        mysql_query(conn, check);
        result = mysql_store_result(conn);
        
        num_fields = mysql_num_fields(result);
        while ((row = mysql_fetch_row(result)))
        {
            for(i = 0; i < num_fields; i++)
            {
                char value[100];
                sprintf(value,"%s", row[i] ? row[i] : "NULL");
                
                total = atof(value);
            }
        }
    }
    else
    {
        printf("DATABASE CONNECTION ERROR!");
    }
    
    mysql_free_result(result);
    mysql_close(conn);
    
    return total;
}

int stGetReusedTotal(SizeEstimate sizeEstimate)
{
    MYSQL *conn;
    MYSQL_RES *result;
    MYSQL_ROW row;
    MYSQL_FIELD *field;
    conn = mysql_init(NULL);
    int num_fields, i;
    int total;
    
    if(mysql_real_connect(conn, sqlServer, sqlUser, sqlPassword, sqlDb, 0, NULL, 0) != NULL)
    {  
        char check[1000];
        sprintf(check, "SELECT SUM(reusedobject.function_lines) AS SUM FROM reusedobject WHERE template_id = %d", sizeEstimate.template_id);
        mysql_query(conn, check);
        result = mysql_store_result(conn);
        
        num_fields = mysql_num_fields(result);
        while ((row = mysql_fetch_row(result)))
        {
            for(i = 0; i < num_fields; i++)
            {
                char value[100];
                sprintf(value,"%s", row[i] ? row[i] : "NULL");
                
                total = atoi(value);
            }
        }
    }
    else
    {
        printf("DATABASE CONNECTION ERROR!");
    }
    
    mysql_free_result(result);
    mysql_close(conn);
    
    return total;
}

void stMain()
{
    BaseProgram baseProgram;
    NewObject newObject[1000];
    ReusedObject reusedObject[1000];
    SizeEstimate sizeEstimate;
        sizeEstimate.template_id = 1;
        sizeEstimate.user_project_id = 1;
    int next = 1;
    int counter = 0;
    int type, size;
    int key, rest;
    
    printf("Base Program\n");
    printf("  Base Size (B): ");
    scanf("%d", &baseProgram.baseSize);
    printf("  LOC Deleted (D): ");
    scanf("%d", &baseProgram.LOCDeleted);
    printf("  LOC Modified (M): ");
    scanf("%d", &baseProgram.LOCModified);
    
    if(baseProgram.baseSize > 0)
    {
        printf("\nProject LOC (P)\n");
        printf("Total Base Additions: 0\n");
    }
    
    printf("\nNew Objects (NO)");
    
    while(next == 1)
    {
        newObject[counter].template_id = sizeEstimate.template_id;
        
        printf("\nFunction name: ");
        scanf("%s", &newObject[counter].function_name);
        printf("Type (enter 0 for list): ");
        scanf("%d", &type);
        
        if(type == 0)
        {
            printf("  1 - Calculation\n");
            printf("  2 - Data\n");
            printf("  3 - I/O\n");
            printf("  4 - Logic\n");
            printf("  5 - Set-up\n");
            printf("  6 - Text\n");
            
            printf("Type: ");
            scanf("%d", &type);
        }
        
        printf("Size (enter 0 for list): ");
        scanf("%d", &size);
        
        if(size == 0)
        {
            printf("  1 - Very Small\n");
            printf("  2 - Small\n");
            printf("  3 - Medium\n");
            printf("  4 - Large\n");
            printf("  5 - Very Large\n");
            
            printf("Size: ");
            scanf("%d", &size);
        }
        
        if(stSetNewObject(newObject[counter], type, size) == 0)    // if input in db properly, counter increases for the next. Else, it doesn't so you can try to input again.
        {
            counter++;
            printf("Press ANY to continue, or BACKSPACE to finish.\n");
            key = getch();

            if(key == BACKSPACE)
            {
                next = 0;
            }
        }
        else
        {
            printf("ERROR - Data wasn't saved into DB. Try again.\n");
        }      
    }
    
    next = 1;
    counter = 0;
    printf("\nReused Objects");
    
    while(next == 1)
    {
        reusedObject[counter].template_id = sizeEstimate.template_id;
        
        printf("\nFunction name: ");
        scanf("%s", &reusedObject[counter].function_name);
        printf("Function lines: ");
        scanf("%f", &reusedObject[counter].function_lines);
        
        if(stSetReusedObject(reusedObject[counter]) == 0)    // if input in db properly, counter increases for the next. Else, it doesn't so you can try to input again.
        {
            counter++;
            printf("Press ANY to continue, or BACKSPACE to finish.\n");
            key = getch();

            if(key == BACKSPACE)
            {
                next = 0;
            }
        }
        else
        {
            printf("ERROR - Data wasn't saved into DB. Try again.\n");
        }      
    }
    
    float b0, b1, projectedLOC, estimatedNewAndChangedLOC, estimatedTotalLOC;
    
    projectedLOC = stGetTotalNewObjects(sizeEstimate);
    
    printf("\nProjected LOC (P): %f\n", projectedLOC);
    printf("Regression Parameter B0: ");
    scanf("%f", &b0);
    printf("Regression Parameter B1: ");
    scanf("%f", &b1);
    estimatedNewAndChangedLOC = b0+b1*(projectedLOC+baseProgram.LOCModified);
    printf("Estimated New and Changed LOC (N): %f\n", estimatedNewAndChangedLOC); //should also be inserted in the DB, kase kinukuha to ng PPS.
    estimatedTotalLOC = estimatedNewAndChangedLOC + baseProgram.baseSize - baseProgram.LOCDeleted - baseProgram.LOCModified + stGetReusedTotal(sizeEstimate);
    printf("Estimated Total LOC (T): %f\n", estimatedTotalLOC);
}

int main()
{
    stMain();
    printf("END");
    getch();
}
